#include "MyGame.h"
#include "..\Entities\Background.h"
#include "..\Entities\Shot.h"
#include "..\Entities\Ship.h"
#include "..\Entities\PlannerEnemy.h"
#include "..\Entities\ReactiveEnemy.h"
#include "..\Entities\GameHUD.h"
#include "..\Scene\SceneManager.h"
#include "..\Scene\SceneNode.h"
#include "..\Dependencies.h"
#include "..\Audio\Sound.h"
#include "..\Audio\AudioManager.h"
#include "../GUI/GUIManager.h"

MyGame::MyGame(WNDPROC WndProc) : GameEngine(WndProc) {
	AudioManager::Instance()->load("explosion.ogg");
	AudioManager::Instance()->load("backgroundmusic.ogg");
	AudioManager::Instance()->load("Heartbomb_explosion.ogg");
	AudioManager::Instance()->load("shot.ogg");
	AudioManager::Instance()->load("pink_panther.ogg");
	env = new TyrianEnvironment();

	GUIManager::Instance()->addMenuOption("New Game");
	GUIManager::Instance()->addMenuOption("Load Game");
	GUIManager::Instance()->addMenuOption("Save Game");
	GUIManager::Instance()->addMenuOption("Quit Game");

	GUIManager::Instance()->addMenuInfo("[W], [S], [A], [D] to move");
	GUIManager::Instance()->addMenuInfo("[F] to fire shots");
	GUIManager::Instance()->addMenuInfo("[UP], [DOWN], to switch between options");
	GUIManager::Instance()->addMenuInfo("[ENTER] to select an option");
	GUIManager::Instance()->addMenuInfo("[P] to pause/unpause game");
	GUIManager::Instance()->addMenuInfo("[M] to go to game menu");
	GUIManager::Instance()->addMenuInfo("[K] to quick save");
	GUIManager::Instance()->addMenuInfo("[L] to quick load");
	GUIManager::Instance()->addMenuBckgnd("assets/menubackground.raw");

}

void MyGame::create(WNDPROC WndProc)
{
	if (_instance == NULL)
	{
		_instance = new MyGame(WndProc);
	}
}

void MyGame::destroy()
{
	delete Instance();
}

MyGame* MyGame::Instance () {
	return (MyGame *) GameEngine::Instance();
}

MyGame::~MyGame() {
}

void MyGame::createScene() {
	
	int maxFrequency = 70;
	Camera * camera = new Camera(maxFrequency);
	SceneManager::Instance()->setCamera(camera);
	camera->setMySceneNode(SceneManager::Instance()->getRootSceneNode());

	COLOR defaultcolor = {1,1,1};
	ORIENTATION orientationOfBackground = {10,{0,0,0}};
	POINT3D positionOfBackground = {-20.0f,-15.0f,-35.0f};

	POINT3D positionOfShip = {0.0f,-13.0f,-34.0f};						
	ORIENTATION orientationOfShip = {50,{0,0,0}};

	POINT3D positionOfRE = {3.0f, 12.0f,-34.0f};						
	ORIENTATION orientationOfRE = {180,{1,0,0}};
	
	POINT3D positionOfPE = {0.0f, 10.0f,-34.0f};							
	ORIENTATION orientationOfPE = {810,{1,0,0}};

	COLOR shipHPcolor = {1,0,0};
	POINT3D positionOfshipHP = {0.0f,0.0f,-34.0f};						
	ORIENTATION orientationOfshipHP = {10,{0,0,0}};

	this->createEntity(SceneManager::Instance()->getRootSceneNode(),0,BACKGROUND,maxFrequency,"background",orientationOfBackground,positionOfBackground,defaultcolor);
	this->createEntity(SceneManager::Instance()->getRootSceneNode(),0,SHIP,40,"ship",orientationOfShip,positionOfShip,defaultcolor);
	this->createEntity(SceneManager::Instance()->getRootSceneNode(),0,REACTIVEENEMY,20,"reactiveenemy",orientationOfRE,positionOfRE,defaultcolor);
	this->createEntity(SceneManager::Instance()->getRootSceneNode(),0,REACTIVEENEMY,20,"reactiveenemy2",orientationOfRE,positionOfRE,defaultcolor);
	//this->createEntity(SceneManager::Instance()->getRootSceneNode(),0,PLANNERENEMY,65,"plannerenemy",orientationOfPE,positionOfPE,defaultcolor);
	this->createEntity(SceneManager::Instance()->getRootSceneNode(),0,GAMEHUD,maxFrequency,"gameHUD",orientationOfshipHP,positionOfshipHP,shipHPcolor);
				
	AudioManager::Instance()->setBackgroundSound("pink_panther.ogg");
	AudioManager::Instance()->playBackgroundSound();

	this->highScore = this->getHighscore();
	this->score = 0;
}
void MyGame::deleteScene(){
	AudioManager::Instance()->stopAll();
	SceneManager::Instance()->clearScene();
}

void MyGame::createCamera(int maxFreq, int rootChilds) {
	//The maximum update frequency for our entities
	Camera * camera = new Camera(maxFreq);
	SceneManager::Instance()->setCamera(camera);
	camera->setMySceneNode(SceneManager::Instance()->getRootSceneNode());
	camera->getMySceneNode()->setChildsToCreate(rootChilds);
	container.push_back(camera);
}

GameEntity* MyGame::createEntity(SceneNode *sceneNode, int nrOfChilds, int type, int maxFrequency, std::string name, ORIENTATION orientation, POINT3D position, COLOR color) {
	int childsToCreate;
	GameEntity * entityObject;
	std::list<GameEntity *>::const_iterator it;
	switch(type) {
		case SHIPSHOT: entityObject = new Shot(maxFrequency, name);
			break;
		case BACKGROUND: {
			POINT3D positionOfBackground = {-20.0f,-15.0f,-35.0f};
			position = positionOfBackground;
			entityObject = new Background(maxFrequency, name);
			break;
		}
		case SHIP: entityObject = new Ship(maxFrequency, name);
			break;
		case PLANNERENEMY: entityObject = new PlannerEnemy(maxFrequency, name);
			break;
		case REACTIVEENEMY: entityObject = new ReactiveEnemy(maxFrequency, name);
			break;
		case GAMEHUD: entityObject = new GameHUD(maxFrequency, name);

	}
	if(sceneNode == NULL) {
		if(container.size() > 0) {
			it = container.end();
			do {
				it--;
				childsToCreate = (*it)->getMySceneNode()->getChildsToCreate();
				if(childsToCreate > 0) {
					sceneNode = (*it)->getMySceneNode()->createChildSceneNode();
					(*it)->getMySceneNode()->setChildsToCreate(--childsToCreate);
					break;
				}
			}
			while(it != container.begin());
		}

	}
	else sceneNode = sceneNode->createChildSceneNode();

	entityObject->setColor(color);
	entityObject->setMaxFrequency(maxFrequency);
	sceneNode->addEntity(entityObject);
	sceneNode->setOrientation(orientation);
	sceneNode->setPosition(position);
	sceneNode->setChildsToCreate(nrOfChilds);
	container.push_back(entityObject);

	return entityObject;
}

void MyGame::cleanContainer() {
	this->container.clear();
}

TyrianEnvironment * MyGame::getEnv() {
	return env;
}

std::list<GameEntity *> MyGame::getContainer() {
	return container;
}

void MyGame::deleteFromContainer(std::list<GameEntity *> entities) {
	std::list<GameEntity *>::iterator it,it1;				//First search the entities
	std::list<GameEntity *> toEliminate;
	for(it=container.begin(); it != container.end(); ++it) {
		for(it1 = entities.begin() ; it1 != entities.end(); ++it1) {
			if((*it) == (*it1)) {
				toEliminate.push_back(*it1);
			}
		}
	}
	for(it=toEliminate.begin(); it != toEliminate.end(); ++it)
		container.remove(*it);
}


void MyGame::callMethod(char* option) {
	if(strcmp(option,"New Game") == 0) {
		AudioManager::Instance()->stopAll();
		GameEngine::Instance()->deleteScene();
		GameEngine::Instance()->createScene();
		GameEngine::Instance()->setGameState(PLAY);
	}
	else if(strcmp(option,"Load Game") == 0) {
		SceneManager::Instance()->getRootSceneNode()->deleteAllChilderAndEntitiesSceneNode();
		std::ifstream infile("savegame.txt",std::ifstream::in);
		SceneManager::Instance()->getRootSceneNode()->read(infile);
		infile.close();
		loadShipHP();
		//GameEngine::Instance()->onKeyPressed('P');
	}
	else if(strcmp(option,"Save Game") == 0) {
		saveShipHP();
		std::ofstream outfile("savegame.txt");
		SceneManager::Instance()->getRootSceneNode()->write(outfile);
		outfile << "*EOF*";
		outfile.close();
	}
	else if(strcmp(option, "Quit Game") == 0) {
		AudioManager::Instance()->stopAll();
		GameEngine::Instance()->getRenderer()->KillWindow();
	}
}

int MyGame::getScore() {
	return this->score;
}

int MyGame::getHighscore() {
	int temp;
	std::ifstream infile("highscore.txt",std::ifstream::in);
	infile >> temp;
	infile.close();
	if(temp > 0)
		highScore = temp;
	else highScore = 0;
	return highScore;
}

void MyGame::incScore() {
	this->score += 7.5;
}

void MyGame::saveShipHP() {
	GameHUD *gamehud;
	gamehud = (GameHUD*)SceneManager::Instance()->getEntity("gameHUD");
	float shipHP = gamehud->getShipHP();
	std::ofstream outfile("hudinfo.txt");
	outfile << shipHP;
	outfile << '\n';
	outfile << score;
	outfile.close();
}

void MyGame::saveScore() {
	if(this->score > this->highScore) {
		std::ofstream outfile("highscore.txt");
		outfile << score;
		outfile.close();
	}
	this->score = 0;
}

void MyGame::loadShipHP() {
	float hp;
	int score;
	GameHUD *gamehud;
	gamehud = (GameHUD*)SceneManager::Instance()->getEntity("gameHUD");
	std::ifstream infile("hudinfo.txt",std::ifstream::in);
	infile >> hp;
	infile >> score;
	gamehud->setHP(hp);
	this->score = score;
}